package com.uduemc.biso.node.web.service.html.impl;

import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.core.extities.center.SysComponentType;
import com.uduemc.biso.core.extities.center.SysContainerType;
import com.uduemc.biso.node.core.common.entities.FormComponent;
import com.uduemc.biso.node.core.common.entities.FormContainer;
import com.uduemc.biso.node.core.common.entities.FormData;
import com.uduemc.biso.node.core.entities.SContainerForm;
import com.uduemc.biso.node.core.entities.SContainerQuoteForm;
import com.uduemc.biso.node.core.entities.SProduct;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.web.component.HIComponentUdinComponent;
import com.uduemc.biso.node.web.component.HIContainerUdinComponent;
import com.uduemc.biso.node.web.component.html.HContainerFormmainboxUdin;
import com.uduemc.biso.node.web.component.html.inter.HIComponentFormUdin;
import com.uduemc.biso.node.web.component.html.inter.HIContainerFormUdin;
import com.uduemc.biso.node.web.service.byfeign.FormService;
import com.uduemc.biso.node.web.service.byfeign.SysStaticDataService;
import com.uduemc.biso.node.web.service.html.HFormService;
import com.uduemc.biso.node.web.utils.AssetsResponseUtil;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Service
public class HFormServiceImpl implements HFormService {

    @Resource
    private FormService formServiceImpl;

    @Resource
    private SysStaticDataService sysStaticDataServiceImpl;

    @Resource
    private HIContainerUdinComponent hIContainerUdinComponent;

    @Resource
    private HIComponentUdinComponent hIComponentUdinComponent;

    @Resource
    private HContainerFormmainboxUdin hContainerFormmainboxUdin;

    @Override
    public StringBuilder html(SContainerQuoteForm sContainerQuoteForm) throws IOException {
        return html(sContainerQuoteForm.getContainerId(), sContainerQuoteForm.getFormId(), sContainerQuoteForm.getHostId(), sContainerQuoteForm.getSiteId());
    }

    @Override
    public StringBuilder html(long boxId, long formId, long hostId, long siteId)
            throws IOException {
        FormData formData = formServiceImpl.findOneByFormHostSiteId(formId, hostId, siteId);
        return html(boxId, formData);
    }

    @Override
    public StringBuilder html(long boxId, FormData formData) throws IOException {

        List<FormContainer> listFormContainer = formData.getListFormContainer();

        List<FormContainerParentData> formContainerParentData = FormContainerParentData.getFormContainerParentData(listFormContainer);

        List<StringBuilder> makeHtml = makeHtml(boxId, -1, -1, formContainerParentData, formData, 0L);

        StringBuilder stringBuilder = new StringBuilder("<!-- formData （" + formData.getForm().getId() + "） -->\n");

        if (!CollectionUtils.isEmpty(makeHtml)) {
            makeHtml.forEach(stringBuilder::append);
        }

        return AssetsResponseUtil.htmlCompress(stringBuilder);
    }

    @Override
    public StringBuilder html(SSystem sSystem, SProduct sProduct) throws IOException {
        if (sSystem == null || sProduct == null) {
            return null;
        }
        Long formId = sSystem.getFormId();
        if (formId == null || formId < 1) {
            return null;
        }
        Long hostId = sSystem.getHostId();
        Long siteId = sSystem.getSiteId();
        FormData formData = formServiceImpl.findOneByFormHostSiteId(formId, hostId, siteId);

        if (formData == null) {
            return null;
        }

        List<FormContainer> listFormContainer = formData.getListFormContainer();

        List<FormContainerParentData> formContainerParentData = FormContainerParentData.getFormContainerParentData(listFormContainer);

        List<StringBuilder> makeHtml = makeHtml(-1, sSystem.getId(), sProduct.getId(), formContainerParentData, formData, 0L);

        StringBuilder stringBuilder = new StringBuilder("<!-- formData （" + formData.getForm().getId() + "） -->\n");

        if (CollUtil.isNotEmpty(makeHtml)) {
            makeHtml.forEach(stringBuilder::append);
        }

        return AssetsResponseUtil.htmlCompress(stringBuilder);
    }

    private List<StringBuilder> makeHtml(long boxId, long systemId, long systemItemId, List<FormContainerParentData> formContainerParentData, FormData formData, long parentId)
            throws IOException {
        List<FormContainer> listFormContainer = getChildrenData(formContainerParentData, parentId);
        if (CollUtil.isEmpty(listFormContainer)) {
            return emptyListFormContainer(parentId, formContainerParentData, formData);
        } else {
            List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
            listFormContainer.forEach(item -> {
                StringBuilder stringBuilder = new StringBuilder();
                Long id = item.getContainerForm().getId();

                // 子节点的所有渲染html内容
                List<StringBuilder> makeHtml = null;
                try {
                    makeHtml = makeHtml(boxId, systemId, systemItemId, formContainerParentData, formData, id);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                SContainerForm containerForm = item.getContainerForm();
                Long typeId = containerForm.getTypeId();
                SysContainerType sysContainerType = null;
                try {
                    sysContainerType = sysStaticDataServiceImpl.getContainerTypeInfoById(typeId);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (sysContainerType != null) {
                    // 判断是否是 formmainbox 表单主容器组件
                    if (HContainerFormmainboxUdin.FormContainerTypeID == sysContainerType.getId()) {
                        stringBuilder.append(hContainerFormmainboxUdin.html(boxId, systemId, systemItemId, formData.getForm(), item, makeHtml));
                    } else {
                        HIContainerFormUdin containerUdin = hIContainerUdinComponent.getHIContainerFormUdinByName(sysContainerType.getType());
                        if (containerUdin != null) {
                            StringBuilder html = containerUdin.html(formData.getForm(), item, makeHtml);
                            stringBuilder.append(html);
                        }
                    }
                }
                arrayList.add(stringBuilder);
            });

            return arrayList;
        }
    }

    /**
     * 通过 parentId 找到对应的子项容器数据为空时存在的情况！包含 component 展示组件数据，包含 容器引用表单
     * 数据，什么都没有。通过这三种情况分别进行处理获取到 containerBox 下的 HTML部分 然后进行返回
     *
     * @param parentId
     * @param formContainerParentData
     * @param formData
     * @return
     * @throws IOException
     * @throws JsonProcessingException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    private List<StringBuilder> emptyListFormContainer(long parentId, List<FormContainerParentData> formContainerParentData, FormData formData) {
        if (parentId < 1) {
            return null;
        }
        FormContainer formContainer = null;
        Iterator<FormContainerParentData> iterator = formContainerParentData.iterator();
        while (iterator.hasNext()) {
            FormContainerParentData next = iterator.next();
            Iterator<FormContainer> iteratorFormContainer = next.getData().iterator();
            while (iteratorFormContainer.hasNext()) {
                FormContainer nextFormContainer = iteratorFormContainer.next();
                if (nextFormContainer.getContainerForm().getId() == parentId) {
                    formContainer = nextFormContainer;
                }
            }
        }
        /**
         * 只能 containerFormbox 才有后续的动作
         */
        if (formContainer == null || formContainer.getContainerForm().getId() == null || formContainer.getContainerForm().getBoxId() == null
                || formContainer.getContainerForm().getTypeId() != 7) {
            return null;
        }

        FormComponent formComponent = getChildrenData(formContainer, formData);
        if (formComponent != null) {
            // 获取 component 的HTML渲染内容
            SysComponentType componentType = null;
            try {
                componentType = sysStaticDataServiceImpl.getComponentTypeInfoById(formComponent.getComponentForm().getTypeId());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (componentType != null) {
                if (componentType.getCateType() != null && componentType.getCateType() == (short) 6) {
                    HIComponentFormUdin componentUdin = hIComponentUdinComponent.getHIComponentFormUdinByName(componentType.getType());
                    if (componentUdin != null) {
                        List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
                        arrayList.add(componentUdin.html(formData.getForm(), formComponent));
                        return arrayList;
                    }
                } else {
                    throw new RuntimeException("表单渲染展示组件时，不存在 componentType.getCateType().shortValue() ！= (short) 6 的情况出现！");
                }
            }
        }
        return null;
    }

    /**
     * 通过 parentId 找出对应的子项数据列表
     *
     * @param formContainerParentData
     * @param parentId
     * @return
     */
    private static List<FormContainer> getChildrenData(List<FormContainerParentData> formContainerParentData, long parentId) {
        if (CollectionUtils.isEmpty(formContainerParentData)) {
            return null;
        }
        List<FormContainer> listFormContainer = null;
        Iterator<FormContainerParentData> iterator = formContainerParentData.iterator();
        while (iterator.hasNext()) {
            FormContainerParentData formContainerParent = iterator.next();
            if (formContainerParent.getParentId() == parentId) {
                listFormContainer = formContainerParent.getData();
            }
        }
        return listFormContainer;
    }

    /**
     * 通过参数验证并且获取 formData.getListFormComponent() 数据列表中的 FormComponent 数据
     *
     * @param formContainer
     * @param formData
     * @return
     */
    private static FormComponent getChildrenData(FormContainer formContainer, FormData formData) {
        if (CollectionUtils.isEmpty(formData.getListFormComponent())) {
            return null;
        }
        Iterator<FormComponent> iteratorFormComponent = formData.getListFormComponent().iterator();
        while (iteratorFormComponent.hasNext()) {
            FormComponent formComponent = iteratorFormComponent.next();
            Long containerId = formComponent.getComponentForm().getContainerId();
            Long containerBoxId = formComponent.getComponentForm().getContainerBoxId();
            if (containerId == null || containerBoxId == null) {
                return null;
            }

            if (formContainer.getContainerForm().getId().longValue() == containerId.longValue()
                    && formContainer.getContainerForm().getBoxId().longValue() == containerBoxId.longValue()) {
                return formComponent;
            }
        }
        return null;
    }

    @Data
    @Accessors(chain = true)
    @ToString
    public static class FormContainerParentData {
        private long parentId;
        private List<FormContainer> data;

        public static List<FormContainerParentData> getFormContainerParentData(List<FormContainer> listFormContainer) {
            if (CollectionUtils.isEmpty(listFormContainer)) {
                return null;
            }
            List<FormContainerParentData> listFormContainerParentData = new ArrayList<HFormServiceImpl.FormContainerParentData>();

            Iterator<FormContainer> iterator = listFormContainer.iterator();
            while (iterator.hasNext()) {
                FormContainer next = iterator.next();
                long parentId = next.getContainerForm().getParentId() == null ? 0 : next.getContainerForm().getParentId().longValue();

                // 是否存在
                FormContainerParentData item = null;
                Iterator<FormContainerParentData> iteratorFormContainerParentData = listFormContainerParentData.iterator();
                while (iteratorFormContainerParentData.hasNext()) {
                    FormContainerParentData formContainerParentData = iteratorFormContainerParentData.next();
                    if (formContainerParentData.getParentId() == parentId) {
                        item = formContainerParentData;
                        break;
                    }
                }

                if (item == null) {
                    item = new FormContainerParentData();
                    item.setParentId(parentId);
                    item.setData(new ArrayList<>());
                    listFormContainerParentData.add(item);
                }

                item.getData().add(next);
            }

            return listFormContainerParentData;
        }
    }

}
